package model.audio;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;

import model.audio.Interface.AudioStateObservable;
import model.audio.Interface.AudioStateObserver;
import model.audio.Interface.DBObservable;
import model.audio.Interface.DBObserver;
import model.audio.Interface.IAudioCaptureModel;
import model.audio.Interface.ITransmission;
import model.infocenter.ClientUserInformations;


public class AudioCaptureModel implements Runnable,IAudioCaptureModel,DBObservable,AudioStateObservable{
	private TargetDataLine line=null;
	private ITransmission AT=null;
	private boolean isStart;
	private boolean canSend=false;
	private boolean isTalk=false;
	private Thread thread=null;
	private DBAnalysis dbAnalysis=null;
	private DBObserver dbObserver=null;
	private AudioStateObserver asObserver=null;
	private SoundProcessor SP=null;
	
	public static final int MAX_DB=70;
	public static final int BUFFER_LENGTH=512;        //每次分析并发送的字节长度
	public static final int MAX_WAIT_TIME=1000;       //声音分贝未达到DBA_TO_SEND时最多持续传输
	public static final float SAMPLE_RATE=4096;       //采样率
	public static final int SAMPLE_SIZE_IN_BITS=8;    //一个样本位数
	public static final int CHANNELS=1;               //声道数
	public static final double DBA_TO_SEND=50;         //达到此分贝值就传送
	public static final int TRANSLATE_NUM=256;        //用来将每20微帕斯卡量化为1
	
	public AudioCaptureModel(ITransmission AT){
		this.AT=AT;
		isStart=false;
		AudioFormat format =new AudioFormat(SAMPLE_RATE,SAMPLE_SIZE_IN_BITS,CHANNELS,true,true);
        DataLine.Info info = new DataLine.Info(TargetDataLine.class,format);
        try {
        	line = (TargetDataLine) AudioSystem.getLine(info);
			line.open(format);
		} catch (LineUnavailableException e) {
			e.printStackTrace();
		}
        dbAnalysis=new DBAnalysis(SAMPLE_RATE);
        SP=new SoundProcessor(SAMPLE_RATE);
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		canSend=true;
		byte temp[]=new byte[BUFFER_LENGTH];
		long startTime=System.currentTimeMillis();
		while(isStart&&!thread.isInterrupted()){
			line.read(temp, 0, temp.length);           
			
			temp=SP.process(temp);   //处理声音
			
			double dba=dbAnalysis.getDBA(quantificat(temp));         //
	        updateDB(dba);
			
			if(dba>DBA_TO_SEND){
				if(canSend==false){
					canSend=true;
				}
				startTime=System.currentTimeMillis();
			}
			updateAudioState();
			if(canSend){
				AT.sendAudioData(temp);
			}
			if((System.currentTimeMillis()-startTime)>MAX_WAIT_TIME){     //维持MAX_WAIT_TIME毫秒
				canSend=false;
			}	
		}
	}
	
	private void updateDB(double dba){
		if(dbObserver!=null){
			dbObserver.setDB(dba);
		}
	}
	
	private void updateAudioState(){
		if(asObserver!=null){
			if(canSend!=isTalk){
				isTalk=canSend;
				InetSocketAddress ad=null;
				try {
					ad=new InetSocketAddress(InetAddress.getByName(ClientUserInformations.getInstance().getIp()),AudioTransmissionModel.PORT);
				} catch (UnknownHostException e) {
					e.printStackTrace();
				}
				if(ad!=null){
					asObserver.updateAudioSessionState(ad, isTalk);
				}
			}
		}	
	}

	@Override
	public void setMicroVolume(float value) {
		// TODO Auto-generated method stub
		SP.setMicroVolume(value);
	}

	@Override
	public void startAudioCapture() {
		// TODO Auto-generated method stub
		if(thread == null || !thread.isAlive()){
			thread = new Thread(this);
			line.start();
			thread.start();
			isStart = true;
		}
	}

	@Override
	public void stopAudioCapture() {
		// TODO Auto-generated method stub
		thread.interrupt();
		line.stop();
		line.close();
		isStart = false;
	}

	@Override
	public void addObserver(DBObserver dbObserver) {
		// TODO Auto-generated method stub
		this.dbObserver=dbObserver;
	}

	@Override
	public void addObserver(AudioStateObserver asObserver) {
		// TODO Auto-generated method stub
		this.asObserver=asObserver;
	}
	
	private int[] quantificat(byte []data){  //将8bits 量化为16bits
		int [] result=new int[data.length];
		for(int i=0;i<data.length;i++){
			result[i]=data[i]*TRANSLATE_NUM;
		}
		return result;
	}
	
	public static void main(String args[]) throws UnknownHostException{
		ArrayList<InetSocketAddress> ads=new ArrayList<InetSocketAddress>();
		InetSocketAddress ad1=new InetSocketAddress(InetAddress.getByName("127.0.0.1"), AudioTransmissionModel.PORT);
		ads.add(ad1);
		AudioMixerModel AMM=new AudioMixerModel();
		AudioTransmissionModel ATM=new AudioTransmissionModel(AMM, null, AudioCaptureModel.BUFFER_LENGTH);
		ATM.updateAddresses(ads);
		AudioCaptureModel ACM=new AudioCaptureModel(ATM);
		//ATM.connect(123111);
		ATM.startAudioTransmission();
		ACM.startAudioCapture();
		/*byte b=127;
		byte a=23;
		byte c=(byte) (a+b);
		System.out.println(c);*/
	}

}
